package cqg.processor;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cqg.CqgReport;

/**
 * Implementation of ProcessorService.
 * <br><br>
 * @author Julio César Pérez Arques
 * @see ProcessorService
 */
public class ProcessorServiceImpl implements ProcessorService {
	private static final Logger logger = LoggerFactory.getLogger(ProcessorServiceImpl.class);
	
	protected Map<String, Processor> processorsMap;
	protected XMLInputFactory xmlInputFactory;
	protected XmlFileSearcher xmlFileSearcher;
	
	public ProcessorServiceImpl(Map<String, Processor> processorsMap) {
		this.processorsMap = processorsMap;
		xmlInputFactory = XMLInputFactory.newInstance();
		xmlFileSearcher = new XmlFileSearcher();
	}

	@Override
	public Collection<CqgReport> process(String path) {
		Collection<CqgReport> cqgReports = new LinkedList<CqgReport>();
		
		List<String> xmlFilePaths = xmlFileSearcher.search(path);
		
		String processorKey = null;
		Processor processor = null;
		
		for (String xmlFilePath : xmlFilePaths) {			
			try {
				processorKey = parseRootElementName(xmlFilePath);
				processor = processorsMap.get(processorKey);
				cqgReports.add(processor.process(xmlFilePath));
			} catch (Exception e) {
				logger.warn(e.getMessage(), e);
				continue;
			}
		}
		
		return cqgReports;
	}
	
	private String parseRootElementName(String xmlFilePath)
			throws FileNotFoundException, XMLStreamException {
		InputStream in = new FileInputStream(xmlFilePath);
		XMLEventReader eventReader = xmlInputFactory.createXMLEventReader(in);
		while (eventReader.hasNext()) {
			XMLEvent event = eventReader.nextEvent();
			if (event.isStartElement()) {
				StartElement startElement = event.asStartElement();
				return startElement.getName().getLocalPart();
			}
		}
		return null;
	}
}
